#ifndef _MATHEMATICS_H_
#define _MATHEMATICS_H_

#include "common.h"

// Pi for angular calculations (D3DX_PI is an alternative)
static const float PH_PI			= 		3.14159f;

// Roundoff error to be ignored in floating point number comparisons
static const float PH_EPSILON		=		0.00001f;

//////////////////////////////////////////////////////////////////////////
// D3DXVECTOR2 Functions
#pragma region D3DXVECTOR2_FUNCTIONS
D3DXINLINE D3DXVECTOR2* D3DXVec2Zero(D3DXVECTOR2* pOut)
{
#ifdef D3DX_DEBUG
	if(!pOut)
		return NULL;
#endif

	pOut->x = 0.0f;	pOut->y = 0.0f;
	return pOut;
}

D3DXINLINE D3DXVECTOR2* D3DXVec2Identity(D3DXVECTOR2* pOut)
{
#ifdef D3DX_DEBUG
	if(!pOut)
		return NULL;
#endif

	pOut->x = 1.0f;	pOut->y = 1.0f;
	return pOut;
}
#pragma endregion
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// PHVEC3 Functions
#pragma region PHVEC3_FUNCTIONS
D3DXINLINE PHVEC3* D3DXVec3Zero(PHVEC3* pOut)
{
#ifdef D3DX_DEBUG
	if(!pOut)
		return NULL;
#endif

	pOut->x = 0.0f;	pOut->y = 0.0f;	pOut->z = 0.0f;
	return pOut;
}

D3DXINLINE PHVEC3* D3DXVec3Identity(PHVEC3* pOut)
{
#ifdef D3DX_DEBUG
	if(!pOut)
		return NULL;
#endif

	pOut->x = 1.0f;	pOut->y = 1.0f;	pOut->z = 1.0f;
	return pOut;
}
#pragma endregion
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// D3DXVECTOR4 Functions
#pragma region D3DXVECTOR4_FUNCTIONS
D3DXINLINE D3DXVECTOR4* D3DXVec4Zero(D3DXVECTOR4* pOut)
{
#ifdef D3DX_DEBUG
	if(!pOut)
		return NULL;
#endif

	pOut->x = 0.0f;	pOut->y = 0.0f;	pOut->z = 0.0f; pOut->w = 0.0f;
	return pOut;
}

D3DXINLINE D3DXVECTOR4* D3DXVec4Identity(D3DXVECTOR4* pOut)
{
#ifdef D3DX_DEBUG
	if(!pOut)
		return NULL;
#endif

	pOut->x = 1.0f;	pOut->y = 1.0f;	pOut->z = 1.0f; pOut->w = 1.0f;
	return pOut;
}
//////////////////////////////////////////////////////////////////////////
#pragma endregion
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// PHMATRIX Functions
#pragma region PHMATRIX_FUNCTIONS
D3DXINLINE PHMATRIX* PHMatrixRotateX(PHMATRIX* pOut, float _XAngle)
{
#ifdef D3DX_DEBUG
	if(!pOut)
		return NULL;
#endif
	
	PHMATRIX _phRotatationX;
	D3DXMatrixRotationX(&_phRotatationX, _XAngle);
	(*pOut) *= _phRotatationX;
	return pOut;
}

D3DXINLINE PHMATRIX* PHMatrixRotateY(PHMATRIX* pOut, float _YAngle)
{
#ifdef D3DX_DEBUG
	if(!pOut)
		return NULL;
#endif
	
	PHMATRIX _phRotatationY;
	D3DXMatrixRotationY(&_phRotatationY, _YAngle);
	(*pOut) *= _phRotatationY;
	return pOut;
}

D3DXINLINE PHMATRIX* PHMatrixRotateZ(PHMATRIX* pOut, float _ZAngle)
{
#ifdef D3DX_DEBUG
	if(!pOut)
		return NULL;
#endif

	PHMATRIX _phRotatationZ;
	D3DXMatrixRotationZ(&_phRotatationZ, _ZAngle);
	(*pOut) *= _phRotatationZ;
	return pOut;
}
#pragma endregion
//////////////////////////////////////////////////////////////////////////


// Converts from degrees to radians
PH_INLINE float DegreeToRadian(float _Degree)
{
	return ((D3DX_PI / 180.0f) * (_Degree));
}

// Converts from radians to degrees
PH_INLINE float RadianToDegree(float _Radian)
{
	return ((180.0f / D3DX_PI) * (_Radian));
}

// Return a random bool value
PH_INLINE bool RandomBoolean() 
{ 
	return ((rand() << 1) / RAND_MAX) != 0;
}

// Return a random int value between min and max
PH_INLINE float RandInt(float _fMin, float _fMax)
{
	return (((rand() / RAND_MAX) * (_fMax - _fMin)) + _fMin);
}

// Return a random float value between min and max
PH_INLINE float RandomFloat(float _fMin, float _fMax)
{
	return (((rand() / (float)RAND_MAX) * (_fMax - _fMin)) + _fMax);
}

PH_INLINE D3DXVECTOR2 RandomD3DXVECTOR2(float _fMin, float _fMax)
{
	D3DXVECTOR2 _pOut;
	for (unsigned i = 0; i < 2; ++i)
		_pOut[i] = RandomFloat(_fMin, _fMax);
	return _pOut;
}

PH_INLINE PHVEC3 RandomPHVEC3(float _fMin, float _fMax)
{
	PHVEC3 _pOut;
	for (unsigned i = 0; i < 3; ++i)
		_pOut[i] = RandomFloat(_fMin, _fMax);
	return _pOut;
}

PH_INLINE D3DXVECTOR4 RandomD3DXVECTOR4(float _fMin, float _fMax)
{
	D3DXVECTOR4 _pOut;
	for (unsigned i = 0; i < 4; ++i)
		_pOut[i] = RandomFloat(_fMin, _fMax);
	return _pOut;
}

PH_INLINE D3DXVECTOR4 RandomNormal(float _fMin, float _fMax)
{
	D3DXVECTOR4 _phOut;
	for (unsigned i = 0; i < 3; ++i)
		_phOut[i] = RandomFloat(_fMin, _fMax);
	_phOut.w = 0;
	return _phOut;
}

PH_INLINE PHMATRIX RandomPHMATRIX(float _fMin, float _fMax)
{
	PHMATRIX _pOut;
	for (unsigned i = 0; i < 16; ++i)
		_pOut[i] = RandomFloat(_fMin, _fMax);
	return _pOut;
}

PH_INLINE RECT Rect(float _fTop, float _fLeft, float _fBottom, float _fRight)
{
	RECT _rRect;
	_rRect.top = (LONG)_fTop;
	_rRect.left = (LONG)_fLeft;
	_rRect.bottom = (LONG)_fBottom;
	_rRect.right = (LONG)_fRight;
	return _rRect;
}

#endif